package com.tool.emulator.common;

/**
 * AccessUnit.java @author tl 2011-6-15
 */
public abstract class AccessUnit {

	private static final ROM[] romValues = new ROM[256];

	static {
		for (int i = 0; i < 256; i++) romValues[i] = new ROM(i);
	}

	public static AccessUnit rom(int val) {
		return romValues[0xff & val];
	}

	public static AccessUnit newRam() {
		return new RAM();
	}

	public static AccessUnit io(int addr, IODevice device) {
		return new IO(addr, device);
	}

	public int directGet() {
		return get();
	}

	public void directSet(int val) {
		set(val);
	}

	public abstract int get();

	public abstract void set(int b);

	public static class IO extends AccessUnit {
		public final int addr;
		public final IODevice device;
		private volatile int val;

		public IO(int addr, IODevice device) {
			this.addr = addr;
			this.device = device;
		}

		@Override
		public int directGet() {
			return this.val;
		}

		@Override
		public void directSet(int val) {
			//ignore
		}

		@Override
		public final int get() {
			return this.val = 0xff & device.read_io(addr);
		}

		@Override
		public final void set(int b) {
			device.write_io(addr, b & 0xff);
		}

	}

	public static class RAM extends AccessUnit {
		private volatile int val = 0;

		public RAM() {
		}

		@Override
		public int get() {
			return this.val;
		}

		@Override
		public void set(int b) {
			this.val = b & 0xff;
		}
	}

	public static class ROM extends AccessUnit {
		private final int val;

		public ROM(int val) {
			super();
			this.val = val & 0xff;
		}

		@Override
		public int get() {
			return this.val;
		}

		@Override
		public void set(int b) {
			//ignore
		}
	}
}
